---
sidebar_label: Upgrading to config v3
sidebar_position: 5
description: Hasura Config V3 project
keywords:
  - hasura
  - docs
  - migration
  - metadata
---

# Upgrading to Hasura Migrations Config v3

## What has changed?

From `v2.0.0` onwards, Hasura allows us to add multiple databases to the
same Hasura instance. If we want to take advantage of multiple databases
we'll have to use a `config v3` project which brings some changes to the
project directory when compared to `config v2`.

`Config v3` also brings updates to the Metadata directory structure to
improve version control and collaboration workflows.To gain these
benefits we recommend upgrading to `config v3` even if you do not intend
to use multiple databases.

Let's try to understand what these changes are.

### Metadata directory

The following is a sample Metadata directory when using `config v3`.

```bash
metadata
├── actions.graphql
├── actions.yaml
├── allow_list.yaml
├── cron_triggers.yaml
├── databases
│   ├── databases.yaml
│   └── s1
│       ├── functions
│       │   ├── functions.yaml
│       │   └── public_search_artists.yaml
│       └── tables
│           ├── public_albums.yaml
│           ├── public_artists.yaml
│           ├── public_genres.yaml
│           ├── public_media_types.yaml
│           ├── public_playlists.yaml
│           ├── public_playlist_track.yaml
│           ├── public_tracks.yaml
│           └── tables.yaml
├── query_collections.yaml
├── remote_schemas.yaml
├── rest_endpoints.yaml
└── version.yaml
```

Notice the introduction of a new `databases` directory. As the name
suggests, this directory will have the Metadata related to all your
databases.

Now let's looks at the contents of `databases/databases.yaml`

```yaml
- name: s1
  kind: postgres
  configuration:
    connection_info:
      database_url:
        from_env: DATABASE_URL
      pool_settings:
        idle_timeout: 180
        max_connections: 50
        retries: 1
  tables: '!include s1/tables/tables.yaml'
  functions: '!include s1/functions/functions.yaml'
```

We can see that we have a database called `s1`, with it's configuration
information and other metadata. Notice the peculiarity of values of
`tables` and `functions` keys. CLI now uses a special syntax to
"include" contents from another file to use it as the value for a
particular key. Here it is `!include s1/tables/tables.yaml` , which
means that CLI will try to fill in value of `tables` from
`s1/tables/tables.yaml`.

Now, If we look at the contents of `s1/tables/tables.yaml` (as shown
below) we understand that it is array whose values are again similarly
sourced from different files.

```yaml
- '!include public_albums.yaml'
- '!include public_artists.yaml'
- '!include public_genres.yaml'
- '!include public_media_types.yaml'
- '!include public_playlist_track.yaml'
- '!include public_playlists.yaml'
- '!include public_tracks.yaml'
```

Let's look at `public_albums.yaml` from the first line above.

```yaml
array_relationships:
  - name: tracks
    using:
      foreign_key_constraint_on:
        column: album_id
        table:
          name: tracks
          schema: public
object_relationships:
  - name: artist
    using:
      foreign_key_constraint_on: artist_id
table:
  name: albums
  schema: public
```

This file specifies the Metadata related to a table called `tracks` in
`public` schema. This means that each table will have it's own file for
it's Metadata specifically. This makes understanding and managing
Metadata related to tables a lot easier.

Also note that Metadata related to custom functions is also managed in a
similar fashion.

When doing a `hasura metadata apply` CLI will inline `!include`
directives with the appropriate contents.

:::info Note

Currently the CLI looks for `!include` directives in `tables` and
`functions` keys only.

:::

### Migrations directory & Seeds directory

There are some changes to `migrations` and `seeds` project directories
in `config v3`. Projects will have child directories corresponding to
Migrations for each connected database. Look at the following example,
the `migrations` directory has a sub directory `default` which
corresponds to the connected database.

```bash
migrations
└── default
  └── 1613987232674_init
      └── up.sql
```

### Changes needed in existing workflows

With the introduction of multiple databases and it's configuration being
stored in metadata, it brings a change of workflow with it.

The steps to apply Migrations and Metadata to a new Hasura instance will
be:

```bash
# first apply Metadata, this will connect Hasura to the configured databases.
hasura metadata apply
# now we can apply Migrations to the connected databases.
hasura migrate apply --all-databases
# follow it with a Metadata reload to make sure Hasura is aware of any newly created database objects.
hasura metadata reload
```

The reason why we have to do `metadata apply` first instead of
`migrate apply` (that we are used to doing in `config v2`) is that if we
do a `migrate apply` first then Hasura might not yet be aware about the
databases it has to connect to as that information is present in
metadata. Earlier we could not start Hasura without a connected
database, but now we can.

As we are now applying Metadata before Migrations, your Metadata might
be in an **inconsistent state** after the initial `metadata apply` till
the `metadata reload` step as some database objects referred to in
Metadata might not be available till the Migrations are applied.

Also, `hasura seeds` and `hasura migrate` commands now accept a required
flag `--database-name`.

:::info Note

As the database connection configuration is now picked up from metadata,
it is important to ensure that all the environments use the same env
vars to store the database connection strings and the Metadata being
applied also uses the appropriate env vars.

:::

## Upgrade steps

The latest version Hasura CLI comes with a convenience script used to
upgrade your CLI project to use `config v3`. Note that this process is
completely independent from your Hasura GraphQL Engine server update
process.

### Pre update checklist / notes

1.  `Config V3` is expected to be used with Hasura GraphQL Engine
    versions `v2.0.0-alpha.1` and above.
2.  During the update process CLI uses the server as the source of
    truth, so make sure your server is up to date.
3.  The update process replaces project Metadata with Metadata on the
    server.

### Step 1: Make a backup

Make sure you take a backup of your Hasura Project before upgrading to
`config v3`.

### Step 2: Upgrade to the latest CLI

Run:

```bash
hasura update-cli
```

If you are updating to a `beta/alpha` release

Run:

```bash
hasura update-cli --version <version>
```

### Step 3: Upgrade Hasura Project to v3

In your project directory, run:

```bash
hasura scripts update-project-v3
```

Your project directory and `config.yaml` should be updated to v3.

The update script will ask for the name of database the current
Migrations and seeds correspond to.

## Continue using config v2

It is possible to continue using `config v2` with Hasura versions
`v2.0.0` and above if you would like to do so.

While using `config v2` with Hasura versions `v2.0.0` and above, as we
have Metadata and Migrations for only a single database, the server
assumes that they belong to a database named `default` and attempts to
apply them to it.

Hence, to continue using `config v2` we need to connect a database to
Hasura GraphQL Engine with the name `default` and then run any metadata
and Migrations commands.

- If you have connected your database using the
  `HASURA_GRAPHQL_DATABASE_URL` env var, the database will be added
  with the name `default` automatically.
- Else you can connect a database with the name `default` following
  the steps [here](/databases/quickstart.mdx).

Post this, the Metadata and Migration commands should work as usual.

:::info Note

Ensure the `version` key in `config.yaml` is set to `2` while using
`config v2`

:::
